(ns ura.style
  (:require
   [reagent.core :as r]
   [reagent.dom :as rd]
   [stylefy.core :as sty]
   [stylefy.reagent :as stylefy-reagent]

   [ura.common :as uc :refer [log spy]]
   [clojure.string :refer [starts-with? includes? split]]

   [ura.tailwind :as stylemap]
   ))



(defn handle-keyvalue
  "
  :[k v] ->{:style {:k v}} ;; key查映射表, value 做参数执行
  "
  [k v]
  (let [styleName (get stylemap/keymap k k)
        opt (get stylemap/styleOpt styleName)

        stvalue (clojure.string/replace v #"\:" " ")
        ]
    (if (nil? opt) {:style {styleName stvalue}}
        {:style (opt styleName stvalue)}
        )
    )
  )

(defn handle-keyword
  "
  :.aaa -> {:class aaa}
  :flex -> {:style {:display :flex}} ;; 查询映射表
  "
  [kw]
  (let [k (name kw)]
    (cond
      (starts-with? k ".") {:class (subs k 1)}
      
      (includes? k "=") (let [kv (split k "=")
                              stname (keyword (first kv))
                              stvalue (second kv)
                              ]
                          (handle-keyvalue stname stvalue)
                          )
      ;; sigle keyword type
      :else {:style (stylemap/stylemap kw)}
      )
    )
  )

(defn attr-normal
  " convert all type attr to normal map type:
  [:bbb ccc] -> {:style {:bbb ccc}}
  {:bbb ccc} -> {:attr {:bbb ccc}}
  "
  [a]
  (cond
    (keyword? a) (handle-keyword a)
    (or (list? a)
        (vector? a)
        ) {:style (apply hash-map a)} ;; TODO convery list to key-value list and use handle-keyvalue
    (map? a) {:attr a}
    nil? nil
    :else (do (log "invalid data type" a) nil)
    )
  )


(defn attr
  "useage:
  class: :.c1     --> {:class c1}
  style: :w=12px
         :w-12
         :width=12px
         [:width \"12px\"]
         [:width :12px]
    attr {:on-click ...}
  inline style: {:style {:width :10px}}
  return: a map contains genereated class, attr, inline style
  "
  [& params]
  (let [firstParam (first params)
        isClassName (string? firstParam)
        styleParams (if isClassName (rest params) params)
        dataList (map attr-normal styleParams)
        class (map :class dataList)
        style (apply merge (map :style dataList))
        attr (apply merge (map :attr dataList))
        ]
    (if isClassName
      (do 
        (sty/class firstParam (if (nil? style) {} style))
        (merge attr {:class (conj class firstParam)})
        )
      (merge {:class class :style style} attr)
      )
    )
  )


(defn class
  " genreate a class by params with className
  "
  [className & params]
  (let [
        dataList (map attr-normal params)
        class (conj (map :class dataList) className)
        style (apply merge (map :style dataList))
        ]
    (log "class styles: " params dataList class style)
    (sty/class className (if (nil? style) {} style))
    )
  className
  )


(defn cls
  "see ./class"
  [className & params]
  (apply class (into [className] params))
  )


(defn StyleTest []
  [:div (attr
         :.c1 ;;class
         :w=23px
         :w=2
         :h-12
         :mt-2
         :px-5
         :py-20
         [:padding-bottom "10px"]
         [:padding-left :10px]
         
         {:on-click #(log "click!")}
         {:style {
                  :margin-bottom "10px"
                  :margin-right :10px
                  }
          }
         )
   "abc" 

   [:span (attr :bg-red-100) "red"]
   [:span (attr :bg-red-200) "red"]
   [:span (attr :bg-red-300) "red"]
   [:span (attr :bg-red-400) "red"]
   [:span (attr :bg-red-500) "red"]
   [:span (attr :bg-red-600) "red"]
   [:span (attr :bg-red-700) "red"]
   [:span (attr :bg-red-800) "red"]
   [:span (attr :bg-red-900) "red"]
   [:span (attr :bg-red-10) "red"]
   [:span (attr :bg-red-11) "err"] ;; error test
   [:span (attr ) "err2"]
   ]
  )

(defn showcolor []
  
  )
